From 31aae62f9ae7510b1cb5a9de6bf4d384eb37825a Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 21 Apr 2023 20:36:07 +0200 Subject: [PATCH] x11: Move window construction to ::constructed() --- gdk/x11/gdksurface-x11.c | 524 +++++++++++++++++++++------------------ 1 file changed, 288 insertions(+), 236 deletions(-) diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c index b190b8ff34..5488b3fd7b 100644 --- a/gdk/x11/gdksurface-x11.c +++ b/gdk/x11/gdksurface-x11.c @@ -777,133 +777,18 @@ gdk_x11_surface_end_frame (GdkSurface *surface) * X11 specific implementations of generic functions * *****************************************************/ -static void -gdk_x11_surface_finalize (GObject *object) -{ - GdkX11Surface *impl; - - g_return_if_fail (GDK_IS_X11_SURFACE (object)); - - impl = GDK_X11_SURFACE (object); - - if (impl->toplevel->in_frame) - unhook_surface_changed (GDK_SURFACE (impl)); - - g_signal_handlers_disconnect_by_func (GDK_SURFACE (impl), - gdk_x11_toplevel_state_callback, - NULL); - g_signal_handlers_disconnect_by_func (GDK_SURFACE (impl), - gdk_x11_toplevel_event_callback, - NULL); - - _gdk_x11_surface_grab_check_destroy (GDK_SURFACE (impl)); - - if (!GDK_SURFACE_DESTROYED (impl)) - { - GdkDisplay *display = GDK_SURFACE_DISPLAY (GDK_SURFACE (impl)); - - _gdk_x11_display_remove_window (display, impl->xid); - if (impl->toplevel && impl->toplevel->focus_window) - _gdk_x11_display_remove_window (display, impl->toplevel->focus_window); - } - - g_clear_pointer (&impl->surface_is_on_monitor, g_list_free); - g_clear_handle_id (&impl->compute_size_source_id, g_source_remove); - g_clear_pointer (&impl->toplevel_layout, gdk_toplevel_layout_unref); - - g_free (impl->toplevel); - - if (impl->cursor) - g_object_unref (impl->cursor); - - G_OBJECT_CLASS (gdk_x11_surface_parent_class)->finalize (object); -} - -typedef struct { - GdkDisplay *display; - Pixmap pixmap; -} FreePixmapData; - -static void -free_pixmap (gpointer datap) -{ - FreePixmapData *data = datap; - - if (!gdk_display_is_closed (data->display)) - { - XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display), - data->pixmap); - } - - g_object_unref (data->display); - g_free (data); -} - -static void -attach_free_pixmap_handler (cairo_surface_t *surface, - GdkDisplay *display, - Pixmap pixmap) -{ - static const cairo_user_data_key_t key; - FreePixmapData *data; - - data = g_new (FreePixmapData, 1); - data->display = g_object_ref (display); - data->pixmap = pixmap; - - cairo_surface_set_user_data (surface, &key, data, free_pixmap); -} - -/* Cairo does not guarantee we get an xlib surface if we call - * cairo_surface_create_similar(). In some cases however, we must use a - * pixmap or bitmap in the X11 API. - * These functions ensure an Xlib surface. - */ -cairo_surface_t * -_gdk_x11_display_create_bitmap_surface (GdkDisplay *display, - int width, - int height) -{ - cairo_surface_t *surface; - Pixmap pixmap; - - pixmap = XCreatePixmap (GDK_DISPLAY_XDISPLAY (display), - GDK_SCREEN_XROOTWIN (GDK_X11_DISPLAY (display)->screen), - width, height, 1); - surface = cairo_xlib_surface_create_for_bitmap (GDK_DISPLAY_XDISPLAY (display), - pixmap, - GDK_X11_SCREEN (GDK_X11_DISPLAY (display)->screen)->xscreen, - width, height); - attach_free_pixmap_handler (surface, display, pixmap); - - return surface; -} - -/* Create a surface backed with a pixmap without alpha on the same screen as surface */ -static cairo_surface_t * -gdk_x11_surface_create_pixmap_surface (GdkSurface *surface, - int width, - int height) +static const char * +get_default_title (void) { - GdkDisplay *display; - Display *dpy; - cairo_surface_t *cairo_surface; - Pixmap pixmap; - - display = gdk_surface_get_display (surface); - dpy = GDK_DISPLAY_XDISPLAY (display); + const char *title; - pixmap = XCreatePixmap (dpy, - GDK_SURFACE_XID (surface), - width, height, - DefaultDepth (dpy, DefaultScreen (dpy))); - cairo_surface = cairo_xlib_surface_create (dpy, - pixmap, - DefaultVisual (dpy, DefaultScreen (dpy)), - width, height); - attach_free_pixmap_handler (cairo_surface, display, pixmap); + title = g_get_application_name (); + if (!title) + title = g_get_prgname (); + if (!title) + title = ""; - return cairo_surface; + return title; } static void @@ -925,20 +810,6 @@ set_wm_protocols (GdkSurface *surface) XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (surface), protocols, n); } -static const char * -get_default_title (void) -{ - const char *title; - - title = g_get_application_name (); - if (!title) - title = g_get_prgname (); - if (!title) - title = ""; - - return title; -} - static void check_leader_window_title (GdkDisplay *display) { @@ -1027,8 +898,7 @@ ensure_sync_counter (GdkSurface *surface) } static void -setup_toplevel_window (GdkSurface *surface, - GdkX11Screen *x11_screen) +setup_toplevel_window (GdkSurface *surface) { GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (surface); GdkX11Surface *impl = GDK_X11_SURFACE (surface); @@ -1044,11 +914,11 @@ setup_toplevel_window (GdkSurface *surface, * press events so they don't get sent to child surfaces. */ toplevel->focus_window = create_focus_window (display, xid); - _gdk_x11_display_add_window (x11_screen->display, + _gdk_x11_display_add_window (display, &toplevel->focus_window, surface); - check_leader_window_title (x11_screen->display); + check_leader_window_title (display); /* FIXME: Is there any point in doing this? Do any WM's pay * attention to PSize, and even if they do, is this the @@ -1068,28 +938,28 @@ setup_toplevel_window (GdkSurface *surface, /* if sandboxed, we're likely in a pid namespace and would only confuse the wm with this */ long pid = getpid (); XChangeProperty (xdisplay, xid, - gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"), + gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"), XA_CARDINAL, 32, PropModeReplace, (guchar *)&pid, 1); } - leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window; + leader_window = GDK_X11_DISPLAY (display)->leader_window; if (!leader_window) leader_window = xid; XChangeProperty (xdisplay, xid, - gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"), + gdk_x11_get_xatom_by_name_for_display (display, "WM_CLIENT_LEADER"), XA_WINDOW, 32, PropModeReplace, (guchar *) &leader_window, 1); if (toplevel->focus_window != None) XChangeProperty (xdisplay, xid, - gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"), + gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME_WINDOW"), XA_WINDOW, 32, PropModeReplace, (guchar *) &toplevel->focus_window, 1); - if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0) - gdk_x11_surface_set_user_time (surface, GDK_X11_DISPLAY (x11_screen->display)->user_time); + if (GDK_X11_DISPLAY (display)->user_time != 0) + gdk_x11_surface_set_user_time (surface, GDK_X11_DISPLAY (display)->user_time); ensure_sync_counter (surface); @@ -1193,6 +1063,179 @@ typedef enum static void gdk_x11_surface_set_title (GdkSurface *surface, const char *title); +static void +gdk_x11_surface_constructed (GObject *object) +{ + GdkX11Surface *self = GDK_X11_SURFACE (object); + GdkSurface *surface = GDK_SURFACE (self); + GdkDisplay *display = gdk_surface_get_display (surface); + GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); + XClassHint *class_hint; + + g_assert (self->xid); + + g_object_ref (surface); + _gdk_x11_display_add_window (display, &self->xid, surface); + + self->surface_scale = display_x11->screen->surface_scale; + + gdk_surface_set_egl_native_window (surface, (void *) self->xid); + + gdk_x11_surface_set_title (surface, get_default_title ()); + + class_hint = XAllocClassHint (); + class_hint->res_name = (char *) g_get_prgname (); + if (display_x11->program_class) + class_hint->res_class = (char *) display_x11->program_class; + else + class_hint->res_class = class_hint->res_name; + XSetClassHint (GDK_DISPLAY_XDISPLAY (display), self->xid, class_hint); + XFree (class_hint); + + setup_toplevel_window (surface); + + gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source, + GDK_SURFACE_XID (surface), GDK_ALL_EVENTS_MASK, + StructureNotifyMask | PropertyChangeMask); + + _gdk_x11_surface_register_dnd (surface); + + connect_frame_clock (surface); + + gdk_surface_freeze_updates (surface); + + G_OBJECT_CLASS (gdk_x11_surface_parent_class)->constructed (object); +} + +static void +gdk_x11_surface_finalize (GObject *object) +{ + GdkX11Surface *impl; + + g_return_if_fail (GDK_IS_X11_SURFACE (object)); + + impl = GDK_X11_SURFACE (object); + + if (impl->toplevel->in_frame) + unhook_surface_changed (GDK_SURFACE (impl)); + + g_signal_handlers_disconnect_by_func (GDK_SURFACE (impl), + gdk_x11_toplevel_state_callback, + NULL); + g_signal_handlers_disconnect_by_func (GDK_SURFACE (impl), + gdk_x11_toplevel_event_callback, + NULL); + + _gdk_x11_surface_grab_check_destroy (GDK_SURFACE (impl)); + + if (!GDK_SURFACE_DESTROYED (impl)) + { + GdkDisplay *display = GDK_SURFACE_DISPLAY (GDK_SURFACE (impl)); + + _gdk_x11_display_remove_window (display, impl->xid); + if (impl->toplevel && impl->toplevel->focus_window) + _gdk_x11_display_remove_window (display, impl->toplevel->focus_window); + } + + g_clear_pointer (&impl->surface_is_on_monitor, g_list_free); + g_clear_handle_id (&impl->compute_size_source_id, g_source_remove); + g_clear_pointer (&impl->toplevel_layout, gdk_toplevel_layout_unref); + + g_free (impl->toplevel); + + if (impl->cursor) + g_object_unref (impl->cursor); + + G_OBJECT_CLASS (gdk_x11_surface_parent_class)->finalize (object); +} + +typedef struct { + GdkDisplay *display; + Pixmap pixmap; +} FreePixmapData; + +static void +free_pixmap (gpointer datap) +{ + FreePixmapData *data = datap; + + if (!gdk_display_is_closed (data->display)) + { + XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display), + data->pixmap); + } + + g_object_unref (data->display); + g_free (data); +} + +static void +attach_free_pixmap_handler (cairo_surface_t *surface, + GdkDisplay *display, + Pixmap pixmap) +{ + static const cairo_user_data_key_t key; + FreePixmapData *data; + + data = g_new (FreePixmapData, 1); + data->display = g_object_ref (display); + data->pixmap = pixmap; + + cairo_surface_set_user_data (surface, &key, data, free_pixmap); +} + +/* Cairo does not guarantee we get an xlib surface if we call + * cairo_surface_create_similar(). In some cases however, we must use a + * pixmap or bitmap in the X11 API. + * These functions ensure an Xlib surface. + */ +cairo_surface_t * +_gdk_x11_display_create_bitmap_surface (GdkDisplay *display, + int width, + int height) +{ + cairo_surface_t *surface; + Pixmap pixmap; + + pixmap = XCreatePixmap (GDK_DISPLAY_XDISPLAY (display), + GDK_SCREEN_XROOTWIN (GDK_X11_DISPLAY (display)->screen), + width, height, 1); + surface = cairo_xlib_surface_create_for_bitmap (GDK_DISPLAY_XDISPLAY (display), + pixmap, + GDK_X11_SCREEN (GDK_X11_DISPLAY (display)->screen)->xscreen, + width, height); + attach_free_pixmap_handler (surface, display, pixmap); + + return surface; +} + +/* Create a surface backed with a pixmap without alpha on the same screen as surface */ +static cairo_surface_t * +gdk_x11_surface_create_pixmap_surface (GdkSurface *surface, + int width, + int height) +{ + GdkDisplay *display; + Display *dpy; + cairo_surface_t *cairo_surface; + Pixmap pixmap; + + display = gdk_surface_get_display (surface); + dpy = GDK_DISPLAY_XDISPLAY (display); + + pixmap = XCreatePixmap (dpy, + GDK_SURFACE_XID (surface), + width, height, + DefaultDepth (dpy, DefaultScreen (dpy))); + cairo_surface = cairo_xlib_surface_create (dpy, + pixmap, + DefaultVisual (dpy, DefaultScreen (dpy)), + width, height); + attach_free_pixmap_handler (cairo_surface, display, pixmap); + + return cairo_surface; +} + static void gdk_x11_surface_set_type_hint (GdkSurface *surface, GdkSurfaceTypeHint hint); @@ -1203,20 +1246,6 @@ gdk_x11_display_create_surface (GdkDisplay *display, { GdkSurface *surface; GdkFrameClock *frame_clock; - GdkX11Surface *impl; - GdkX11Screen *x11_screen; - GdkX11Display *display_x11; - - Window xparent; - Display *xdisplay; - - XSetWindowAttributes xattributes; - long xattributes_mask; - XClassHint *class_hint; - - display_x11 = GDK_X11_DISPLAY (display); - x11_screen = GDK_X11_SCREEN (display_x11->screen); - xparent = GDK_SCREEN_XROOTWIN (x11_screen); if (parent) frame_clock = g_object_ref (gdk_surface_get_frame_clock (parent)); @@ -1251,78 +1280,6 @@ gdk_x11_display_create_surface (GdkDisplay *display, g_object_unref (frame_clock); - impl = GDK_X11_SURFACE (surface); - impl->surface_scale = x11_screen->surface_scale; - - xdisplay = x11_screen->xdisplay; - - xattributes_mask = 0; - - impl->override_redirect = FALSE; - - xattributes.background_pixmap = None; - xattributes_mask |= CWBackPixmap; - - xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num); - xattributes_mask |= CWBorderPixel; - - xattributes.bit_gravity = NorthWestGravity; - xattributes_mask |= CWBitGravity; - - xattributes.colormap = gdk_x11_display_get_window_colormap (display_x11); - xattributes_mask |= CWColormap; - - if (surface_type == GDK_SURFACE_DRAG || - surface_type == GDK_SURFACE_POPUP) - { - xattributes.save_under = True; - xattributes.override_redirect = True; - xattributes.cursor = None; - xattributes_mask |= CWSaveUnder | CWOverrideRedirect; - - impl->override_redirect = TRUE; - } - - impl->xid = XCreateWindow (xdisplay, xparent, - 0, 0, 1, 1, - 0, - gdk_x11_display_get_window_depth (display_x11), - InputOutput, - gdk_x11_display_get_window_visual (display_x11), - xattributes_mask, &xattributes); - - g_object_ref (surface); - _gdk_x11_display_add_window (x11_screen->display, &impl->xid, surface); - - gdk_surface_set_egl_native_window (surface, (void *) impl->xid); - - gdk_x11_surface_set_title (surface, get_default_title ()); - if (surface_type == GDK_SURFACE_TOPLEVEL) - gdk_x11_surface_set_type_hint (surface, GDK_SURFACE_TYPE_HINT_NORMAL); - else if (surface_type == GDK_SURFACE_POPUP) - gdk_x11_surface_set_type_hint (surface, GDK_SURFACE_TYPE_HINT_MENU); - - class_hint = XAllocClassHint (); - class_hint->res_name = (char *) g_get_prgname (); - if (display_x11->program_class) - class_hint->res_class = (char *) display_x11->program_class; - else - class_hint->res_class = class_hint->res_name; - XSetClassHint (xdisplay, impl->xid, class_hint); - XFree (class_hint); - - setup_toplevel_window (surface, x11_screen); - - gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source, - GDK_SURFACE_XID (surface), GDK_ALL_EVENTS_MASK, - StructureNotifyMask | PropertyChangeMask); - - _gdk_x11_surface_register_dnd (surface); - - connect_frame_clock (surface); - - gdk_surface_freeze_updates (surface); - return surface; } @@ -2263,7 +2220,7 @@ gdk_x11_surface_focus (GdkSurface *surface, static void gdk_x11_surface_set_type_hint (GdkSurface *surface, - GdkSurfaceTypeHint hint) + GdkSurfaceTypeHint hint) { GdkDisplay *display; Atom atom; @@ -4841,6 +4798,7 @@ gdk_x11_surface_class_init (GdkX11SurfaceClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GdkSurfaceClass *impl_class = GDK_SURFACE_CLASS (klass); + object_class->constructed = gdk_x11_surface_constructed; object_class->finalize = gdk_x11_surface_finalize; impl_class->hide = gdk_x11_surface_hide; @@ -4859,6 +4817,39 @@ gdk_x11_surface_class_init (GdkX11SurfaceClass *klass) impl_class->compute_size = gdk_x11_surface_compute_size; } +static void +gdk_x11_surface_create_window (GdkX11Surface *self, + XSetWindowAttributes *xattributes, + long xattributes_mask) +{ + GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (self)); + GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); + + g_assert (self->xid == 0); + + xattributes->background_pixmap = None; + xattributes_mask |= CWBackPixmap; + + xattributes->border_pixel = BlackPixel (GDK_DISPLAY_XDISPLAY (display), + display_x11->screen->screen_num); + xattributes_mask |= CWBorderPixel; + + xattributes->bit_gravity = NorthWestGravity; + xattributes_mask |= CWBitGravity; + + xattributes->colormap = gdk_x11_display_get_window_colormap (display_x11); + xattributes_mask |= CWColormap; + + self->xid = XCreateWindow (GDK_DISPLAY_XDISPLAY (display), + display_x11->screen->xroot_window, + 0, 0, 1, 1, + 0, + gdk_x11_display_get_window_depth (display_x11), + InputOutput, + gdk_x11_display_get_window_visual (display_x11), + xattributes_mask, xattributes); +} + #define LAST_PROP 1 typedef struct { @@ -4880,6 +4871,27 @@ gdk_x11_popup_init (GdkX11Popup *popup) { } +static void +gdk_x11_popup_constructed (GObject *object) +{ + GdkX11Surface *x11_surface = GDK_X11_SURFACE (object); + GdkSurface *surface = GDK_SURFACE (x11_surface); + XSetWindowAttributes xattributes; + long xattributes_mask; + + xattributes.save_under = True; + xattributes.override_redirect = True; + xattributes_mask = CWSaveUnder | CWOverrideRedirect; + + gdk_x11_surface_create_window (x11_surface, &xattributes, xattributes_mask); + + x11_surface->override_redirect = TRUE; + + G_OBJECT_CLASS (gdk_x11_popup_parent_class)->constructed (object); + + gdk_x11_surface_set_type_hint (surface, GDK_SURFACE_TYPE_HINT_MENU); +} + static void gdk_x11_popup_get_property (GObject *object, guint prop_id, @@ -4930,12 +4942,12 @@ gdk_x11_popup_set_property (GObject *object, } } - static void gdk_x11_popup_class_init (GdkX11PopupClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); + object_class->constructed = gdk_x11_popup_constructed; object_class->get_property = gdk_x11_popup_get_property; object_class->set_property = gdk_x11_popup_set_property; @@ -4995,6 +5007,24 @@ static void gdk_x11_toplevel_init (GdkX11Toplevel *toplevel) { } + +static void +gdk_x11_toplevel_constructed (GObject *object) +{ + GdkX11Surface *x11_surface = GDK_X11_SURFACE (object); + GdkSurface *surface = GDK_SURFACE (x11_surface); + XSetWindowAttributes xattributes; + long xattributes_mask; + + xattributes_mask = 0; + + gdk_x11_surface_create_window (x11_surface, &xattributes, xattributes_mask); + + G_OBJECT_CLASS (gdk_x11_toplevel_parent_class)->constructed (object); + + gdk_x11_surface_set_type_hint (surface, GDK_SURFACE_TYPE_HINT_NORMAL); +} + static void gdk_x11_toplevel_set_property (GObject *object, guint prop_id, @@ -5124,6 +5154,7 @@ gdk_x11_toplevel_class_init (GdkX11ToplevelClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); + object_class->constructed = gdk_x11_toplevel_constructed; object_class->get_property = gdk_x11_toplevel_get_property; object_class->set_property = gdk_x11_toplevel_set_property; @@ -5369,6 +5400,24 @@ G_DEFINE_TYPE_WITH_CODE (GdkX11DragSurface, gdk_x11_drag_surface, GDK_TYPE_X11_S G_IMPLEMENT_INTERFACE (GDK_TYPE_DRAG_SURFACE, gdk_x11_drag_surface_iface_init)) +static void +gdk_x11_drag_surface_constructed (GObject *object) +{ + GdkX11Surface *x11_surface = GDK_X11_SURFACE (object); + XSetWindowAttributes xattributes; + long xattributes_mask; + + xattributes.save_under = True; + xattributes.override_redirect = True; + xattributes_mask = CWSaveUnder | CWOverrideRedirect; + + gdk_x11_surface_create_window (x11_surface, &xattributes, xattributes_mask); + + x11_surface->override_redirect = TRUE; + + G_OBJECT_CLASS (gdk_x11_drag_surface_parent_class)->constructed (object); +} + static void gdk_x11_drag_surface_init (GdkX11DragSurface *surface) { @@ -5377,6 +5426,9 @@ gdk_x11_drag_surface_init (GdkX11DragSurface *surface) static void gdk_x11_drag_surface_class_init (GdkX11DragSurfaceClass *class) { + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->constructed = gdk_x11_drag_surface_constructed; } static gboolean -- 2.30.2